package com.vhall.component.plugin.core.service;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.vhall.component.entity.account.dto.CheckRiskMatchDTO;
import com.vhall.component.entity.account.dto.ExchangeSessionIdDTO;
import com.vhall.component.entity.account.vo.WatchLoginSsoVO;
import com.vhall.component.entity.goods.dto.ProdInfoGuoXinDTO;
import com.vhall.component.entity.goods.dto.SearchProdGuoXinDTO;
import com.vhall.component.entity.guosen.dto.GetTghInfoDTO;
import com.vhall.component.entity.guosen.dto.GuoxinFollowTghDTO;
import com.vhall.component.entity.guosen.enums.GuoXinXtgzstgGetTghInfoResponseEnum;
import com.vhall.component.entity.room.dto.*;
import com.vhall.component.entity.room.enums.RefRankEnum;
import com.vhall.component.entity.room.vo.InvestRefResponseVO;
import com.vhall.component.entity.thirduser.vo.GuoxinInvestmentAdvisorTeamDTO;
import com.vhall.component.framework.common.exception.BusinessException;
import com.vhall.component.plugin.common.constant.RedisKey;
import com.vhall.component.plugin.common.exception.BizErrorCode;
import com.vhall.component.plugin.common.properties.ThirdPartyProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * GuoXinService-国信提供的服务接口
 *
 * @author xing.wang
 * @date 2023/8/8
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class GuoXinService extends BaseHttpService {
    private final ThirdPartyProperties thirdPartyProperties;
    private final RedisTemplate<String,Object> redisTemplate;

    /**
     * 投资依据查询接口
     *
     * @param dto 参数
     * @return
     */
    public JSONObject getInvestRefList(SelectInvestRefDTO dto) {
        String tzyjUrl = thirdPartyProperties.getBusiness().getHost() + thirdPartyProperties.getBusiness().getTzyjUrl();
        long ts = System.currentTimeMillis();
        String sign;
        sign = createSign(ts);
        String urlString = tzyjUrl + "?sign=" + sign
                + "&jgid=" + dto.getOrgCode()
                + "&notesid=" + dto.getNotesid();
        //报告标题 模糊搜索
        String bgbt = dto.getBgbt();
        String jyid = dto.getJyid();
        if (StrUtil.isNotBlank(bgbt)) {
            urlString += "&bgbt=" + bgbt;
        }
        if (StrUtil.isNotBlank(jyid)) {
            urlString += "&jyid=" + jyid;
        }
        return httpRequestGetJsonObject(urlString, "查询投资依据信息");
    }

    /**
     * OA 审核流程查询接口
     *
     * @param dto 参数
     * @return
     */
    public JSONObject getOAFlowList(SelectOAFlowDTO dto) {
        String oaFlowUrl = thirdPartyProperties.getBusiness().getHost() + thirdPartyProperties.getBusiness().getOaFlowUrl();
        long ts = System.currentTimeMillis();
        String sign;
        sign = createSign(ts);
        String urlString = oaFlowUrl + "?sign=" + sign
                + "&notesid=" + dto.getNotesid();
        String title = dto.getTitle();
        String fdId = dto.getFdId();
        if (StrUtil.isNotBlank(title)) {
            urlString += "&title=" + title;
        }
        if (StrUtil.isNotBlank(fdId)) {
            urlString += "&fdId=" + fdId;
        }
        return httpRequestGetJsonObject(urlString, "OA 审核流程查询接口");
    }


    /**
     * 观众端获取用户信息
     *
     * @param vo
     * @return
     */
    public JSONObject getThirdUserInfoWatch(WatchLoginSsoVO vo) {
        String watchUserLoginInfoUrl = thirdPartyProperties.getSso().getWatchUserLoginInfoUrl();
        long ts = System.currentTimeMillis();
        String sign;
        sign = createSign(ts);
        String urlString = watchUserLoginInfoUrl + "?sign=" + sign
                + "&token=" + vo.getGxToken()
                + "&channel=" + vo.getChannel();
        String fundid = vo.getFundid();
        if (StrUtil.isNotBlank(fundid)) {
            urlString += "&fundid=" + fundid;
        }
        return httpRequestGetJsonObject(urlString, "观众端sso登录");
    }

    /**
     * 发送短信
     *
     * @param dto 参数
     * @return
     */
    public JSONObject sendMessge(SendMessgeDTO dto) {
        String sendMessageUrl = thirdPartyProperties.getBusiness().getHost() + thirdPartyProperties.getBusiness().getSendMessageUrl();
        long ts = System.currentTimeMillis();
        String sign = createSign(ts);

        Map<String, Object> param = new HashMap<>();

        param.put("sign", sign);
        param.put("mobile", dto.getMobile());
        param.put("content", dto.getContent());


        String body = httpPostAndPrintLog(sendMessageUrl, param);

        JSONObject data = JSONObject.parseObject(body);
        if (!"0".equals(data.getString("code"))) {
            log.error(MessageFormat.format("国信 发送短信,调用失败: url:{0},param:{1},result:{2}", sendMessageUrl, param.toString(), body));
            throw new BusinessException(BizErrorCode.BIZ_THIRD_FAILED);
        }
        return data.getJSONObject("data");
    }

    /**
     * 发送邮件
     *
     * @param dto 参数
     * @return
     */
    public JSONObject sendEmail(SendEmailDTO dto) {

        String sendEmailUrl = thirdPartyProperties.getBusiness().getHost() + thirdPartyProperties.getBusiness().getSendEmailUrl();
        long ts = System.currentTimeMillis();
        String sign = createSign(ts);

        Map<String, Object> param = new HashMap<>();

        param.put("sign", sign);
        param.put("linkUrl", dto.getLinkUrl());
        param.put("title", dto.getTitle());
        param.put("text", dto.getText());
        param.put("sendto", dto.getSendto());

        String body = httpPostAndPrintLog(sendEmailUrl, param);

        JSONObject data = JSONObject.parseObject(body);
        if (!"0".equals(data.getString("code"))) {
            log.error(MessageFormat.format("国信 发送邮件,调用失败: url:{0},param:{1},result:{2}", sendEmailUrl, param.toString(), body));
            throw new BusinessException(BizErrorCode.BIZ_THIRD_FAILED);
        }
        return data.getJSONObject("data");

    }

    /**
     * 适当性校验接口
     * 接口定义：/xtgzstg/vhall/check_risk_match
     * 请求参数：
     * 参数 类型 是否必
     * 填 长度
     * 描述 示例
     * 值
     * userCode String 是 用户唯一id
     * custid String 是 资金账号（如果已交易登录传交易登录账号，如果未交易登录传绑定账号，如果未绑定需要让客户先绑
     * 定）
     * prdRiskLevel Integer 是 0-无要求，5-R5（高风险）,4-R4（中高风险）,3-R3（中风险）,2-R2（中低风险）,1-R1（低风险）
     * prdInvestType Integer 是 0-无要求，1-固定收益类,2-权益类,3-另类,4-杠杆类,5-复杂或高风险类
     * prdInvestPeriod Integer 是 0-无要求，1-0（含）到1年（含）,2-1（不含）到3年（含）,3-3（不含）到5年（含）,4-5年（不含）以
     * 上
     * prdUseCase Integer 是 0-无，1-融资融券，2-港股通，3-创业板，4-科创板，5-股票期权，6-北交所
     * liveType Integer 是 直播类型   1-投教类、2-投顾类、3-产品类、4-研究所类
     * hgtzz Integer 是 合格投资者要求 0-无限制，1-私募合格投资者，2-资管/小集合合格投资者
     * randomKey String 否 交易串（交易登录），如果有合格投资者要求（hgtzz=1或2）则必传
     * sign String 是
     *
     * @param dto
     * @return
     * 返回参数：
     * 参数 类型 描述 示例值
     * code String 返回码 -1 - 未知错误
     * 0-校验通过
     * 1-校验不通过
     * 2-是国信员工
     * msg String 返回描述
     * data type 不通过下一步操作类型 1-弹出提示信息
     * 2-跳转链接
     * 3-去签署鑫投顾协议
     * 4-去签署研究所服务协议（暂未用到）
     * n-待补充
     * url 跳转地址
     * notice 适当性不通过说明
     */
    public JSONObject checkRiskMatch(CheckRiskMatchDTO dto) {

        String checkRiskMatchUrl = thirdPartyProperties.getBusiness().getHost() + thirdPartyProperties.getBusiness().getCheckRiskMatchUrl();
        long ts = System.currentTimeMillis();
        String sign;
        sign = createSign(ts);
        String custId = StrUtil.isNotBlank(dto.getCustid()) ? dto.getCustid() : "0";
        String urlString = checkRiskMatchUrl + "?sign=" + sign
                + "&channel=" + dto.getChannel()
                + "&userCode=" + dto.getUserCode()
                + "&custid=" + custId
                + "&prdRiskLevel=" + dto.getPrdRiskLevel()
                + "&prdInvestType=" + dto.getPrdInvestType()
                + "&prdInvestPeriod=" + dto.getPrdInvestPeriod()
                + "&prdUseCase=" + dto.getPrdUseCase()
                + "&liveType=" + dto.getLiveType()
                + "&hgtzz=" + dto.getHgtzz();
        String randomKey = dto.getRandomKey();
        if (StrUtil.isNotBlank(randomKey)) {
            urlString += "&randomKey=" + randomKey;
        }
        String methodName = "用户观看校验";
        HttpRequest httpRequest = HttpRequest.get(urlString);
        log.info("调用三方服务{},请求体:{}", methodName, httpRequest.toString());
        HttpResponse execute = null;
        String body;
        try {
            execute = httpRequest.execute();
            body = execute.body();
        } catch (Exception e) {
            log.error("调用三方发生错误{},请求体:{},响应体:{}", methodName, httpRequest.toString(), execute, e);
            throw new BusinessException(BizErrorCode.BIZ_THIRD_FAILED);
        }

        JSONObject bodyJson = JSONObject.parseObject(body);
        String code = bodyJson.getString("code");
        if (!"0".equals(code) && !"1".equals(code) && !"2".equals(code)) {
            log.error("调用三方发生错误{},返回结果不符合预期,请求体:{},响应体:{}", methodName, httpRequest.toString(), execute);
            throw new BusinessException(BizErrorCode.BIZ_THIRD_FAILED);
        }
        JSONObject data = bodyJson.getJSONObject("data");
        log.info("{},返回code:{},结果为:{},当通过校验时 data 为 null", methodName, code, data);
        return data;
    }

    /**
     * 查询产品列表
     *
     * @param dto
     * @return
     */
    public JSONObject searchProd(SearchProdGuoXinDTO dto) {
        String searchProdUrl = thirdPartyProperties.getBusiness().getHost() + thirdPartyProperties.getBusiness().getSearchProdUrl();
        long ts = System.currentTimeMillis();
        String sign;
        sign = createSign(ts);
        String urlString = searchProdUrl + "?sign=" + sign
                + "&notesid=" + dto.getNotesid()
                + "&prdType=" + dto.getPrdType()
                + "&prdQuery=" + dto.getPrdQuery();
        Integer pageSize = dto.getPageSize();
        Integer pageNo = dto.getPageNo();
        if (Objects.nonNull(pageNo)) {
            urlString += "&pageNo=" + pageNo;
        }
        if (Objects.nonNull(pageSize)) {
            urlString += "&pageSize=" + pageSize;
        }
        return httpRequestGetJsonObject(urlString, "查询产品列表");
    }

    /**
     * 产品详情查询
     *
     * @param dto
     * @return
     */
    public JSONArray prodInfo(ProdInfoGuoXinDTO dto) {
        String searchProdUrl = thirdPartyProperties.getBusiness().getHost() + thirdPartyProperties.getBusiness().getProdInfoUrl();
        long ts = System.currentTimeMillis();
        String sign;
        sign = createSign(ts);
        String urlString = searchProdUrl + "?sign=" + sign
                + "&prdCodes=" + dto.getPrdCodes();
        String shareid = dto.getShareid();
        Integer roomId = dto.getRoomId();
        if (StrUtil.isNotBlank(shareid)) {
            urlString+="&shareid=" + shareid;
        }
        if (Objects.nonNull(roomId)) {
            urlString+="&roomid=" + roomId;
        }
        return httpRequestGetJsonArray(urlString, "产品详情查询");
    }

    /**
     * 使用微信的 ticket 换取 session id
     *
     * @param dto
     * @return
     */
    public JSONObject exchangeSessionId(ExchangeSessionIdDTO dto) {
        String wxUmAccessUrl = thirdPartyProperties.getBusiness().getHost() + thirdPartyProperties.getBusiness().getWxUmAccessUrl();
        String urlString = wxUmAccessUrl + "?ticket=" + dto.getTicket();
        String methodName = "使用微信的 ticket 换取 session id";
        HttpRequest httpRequest = HttpRequest.get(urlString);
        log.info("调用三方服务{},请求体:{}", methodName, httpRequest.toString());
        HttpResponse execute = null;
        String body;
        try {
            execute = httpRequest.execute();
            body = execute.body();
        } catch (Exception e) {
            log.error("调用三方发生错误{},请求体:{},响应体:{}", methodName, httpRequest.toString(), execute, e);
            throw new BusinessException(BizErrorCode.BIZ_THIRD_FAILED);
        }
        JSONObject bodyJson = JSONObject.parseObject(body);
        log.info("{},返回结果为:{}", methodName, bodyJson);
        return bodyJson;

    }

    /**
     * 生成 sign
     *
     * @param ts
     * @return
     */
    @NotNull
    private String createSign(long ts) {
        String sign;
        sign = MD5.create().digestHex(thirdPartyProperties.getBusiness().getKey() + ts) + ts;
        return sign;
    }
    public InvestRefResponseVO getInvestRefEntity(SelectInvestRefDTO dto, Integer investRefId) {
        String key = RedisKey.INVEST_REF_INFO_CACHE + investRefId;
        InvestRefResponseVO entity;
        if (redisTemplate.hasKey(key)) {
            JSONObject investRefInfo = (JSONObject) redisTemplate.opsForValue().get(key);
            entity = buildInvestRefInfo(investRefInfo);
        }else{
            JSONObject investRefList = Optional.ofNullable(getInvestRefList(dto)).orElse(new JSONObject());
            JSONArray list = investRefList.getJSONArray("list");
            JSONObject investRefInfo = list.getJSONObject(0);
            redisTemplate.opsForValue().set(key,investRefInfo,1, TimeUnit.MINUTES);
            entity = buildInvestRefInfo(investRefInfo);
        }
        return entity;
    }
    public InvestRefResponseVO buildInvestRefInfo(JSONObject investRefInfo) {
        //依据编号
        String jyid = investRefInfo.getString("jyid");
        //依据类别枚举值
        String jylbId = investRefInfo.getString("jylb_id");
        //依据类别名称
        String jylbName = investRefInfo.getString("jylb_name");
        //依据分类- 文字/语言
        String jyflId = investRefInfo.getString("jyfl_id");
        //依据分类名称
        String jyflName = investRefInfo.getString("jyfl_name");
        //创建人名称
        String yhmc = investRefInfo.getString("yhmc");
        //创建人 id
        String yhid = investRefInfo.getString("yhid");
        //依据内容
        String jynr = investRefInfo.getString("jynr");
        //报告标题
        String bgbt = investRefInfo.getString("bgbt");
        //股票代码
        String stkcode = investRefInfo.getString("stkcode");
        //引用状态 0 未引用 1 已经引用
        String refStatus = investRefInfo.getString("ref_status");
        //依据评级 1推荐、2谨慎推荐、3中性、4回避、5无评级
        String refRank = investRefInfo.getString("ref_rank");
        //引用次数
        String yycs = investRefInfo.getString("yycs");
        //股票名称 = 证券简称
        String stkname = investRefInfo.getString("stkname");
        //发布日期
        String fbrq = investRefInfo.getString("fbrq");
//        2023年12月19日 新增字段
//         发布机构
        String fbjg = investRefInfo.getString("fbjg");
//        建议类型
        String jylx = investRefInfo.getString("jylx");
//        关键字
        String gjz = investRefInfo.getString("gjz");
//        审核人
        String shr = investRefInfo.getString("shr");
//        创建人
        String creater = investRefInfo.getString("creater");
//        审核人资格
        String shrCert = investRefInfo.getString("shr_cert");
//        创建人资格
        String cjrCert = investRefInfo.getString("cjr_cert");
//        创建日期
        String createrTime = investRefInfo.getString("creater_time");
//        有效日期
        String endTime = investRefInfo.getString("end_time");


        InvestRefResponseVO data = new InvestRefResponseVO();
        data.setJyId(jyid);
        data.setRefContent(jynr);
        if (NumberUtil.isNumber(jylbId)) {
            data.setRefType(Integer.parseInt(jylbId));
            data.setRefTypeName(jylbName);
        }
        data.setAuthorId(yhid);
        if (NumberUtil.isNumber(refStatus)) {
            data.setRefStatus(Integer.parseInt(refStatus));
            data.setRefStatusName("1".equals(refStatus) ? "已经引用" : "未引用");
        }
        if (NumberUtil.isNumber(refRank)) {
            int refRankInt = Integer.parseInt(refRank);
            data.setRefRank(refRankInt);
            data.setRefRankName(RefRankEnum.getNameByValue(refRankInt));
        }

        data.setAuthor(yhmc);
        data.setStockCode(stkcode);
        data.setRefTitle(bgbt);
        data.setStkname(stkname);
        data.setFbrq(fbrq);
        if (NumberUtil.isNumber(jyflId)) {
            data.setRefForm(Integer.parseInt(jyflId));
            data.setRefFormName(jyflName);
        }
        if (NumberUtil.isNumber(yycs)) {
            data.setRefNum(Integer.parseInt(yycs));
        }
        data.setFbjg(fbjg);
        data.setJylx(jylx);
        data.setGjz(gjz);
        data.setShr(shr);
        data.setCreater(creater);
        data.setShrCert(shrCert);
        data.setCjrCert(cjrCert);
        data.setCreaterTime(createrTime);
        data.setEndTime(endTime);
        return data;
    }

    /**
     * 发送渠道运营管理平台站内信
     *
     * @param dto 参数
     * @return
     */
    public void sendInnerMessageUrl(SendInnerMessageUrl dto) {

        String sendInnerMessageUrl = thirdPartyProperties.getBusiness().getHost() + thirdPartyProperties.getBusiness().getSendInnerMessageUrl();
        long ts = System.currentTimeMillis();
        String sign = createSign(ts);

        String urlString = sendInnerMessageUrl+"?sign="+sign
                +"&nickName="+dto.getNickName()
                +"&notesid="+dto.getNotesid()
                +"&name="+dto.getName()
                +"&title="+dto.getTitle()
                +"&sendto="+dto.getSendto()
                ;
        if (StringUtils.isNotBlank(dto.getUrl())) {
            urlString = urlString + "&url=" + dto.getUrl();
        }
        httpRequestGetString(urlString,"发送渠道运营管理平台站内信",false);
    }
    /**
     * 查询员工所属投顾IP信息
     *
     * @param dto 参数
     * @return
     */
    public JSONObject getTghInfo(GetTghInfoDTO dto) {
        String tzyjUrl = thirdPartyProperties.getBusiness().getHost() + thirdPartyProperties.getBusiness().getGetTghInfoUrl();
        long ts = System.currentTimeMillis();
        String sign;
        sign = createSign(ts);
        String urlString = tzyjUrl + "?sign=" + sign
                + "&notesid=" + dto.getNotesid();
        //客户的 usercode,用户获取观众是否关注当前投顾
        String userCode = dto.getUserCode();
        if (StrUtil.isNotBlank(userCode)) {
            urlString += "&userCode=" + userCode;
        }
        return httpRequestGetJsonObject(urlString, "查询员工所属投顾IP信息",false);
    }
    /**
     * 关注投顾IP
     *
     * @param dto 参数
     * @return
     */
    public String followTgh(GuoxinFollowTghDTO dto) {
        String followTghUrl = thirdPartyProperties.getBusiness().getHost() + thirdPartyProperties.getBusiness().getFollowTghUrl();
        long ts = System.currentTimeMillis();
        String sign;
        sign = createSign(ts);
        String urlString = followTghUrl + "?sign=" + sign
                + "&zoneId=" + dto.getZoneId()
                + "&opType=" + dto.getOpType()
                + "&userCode=" + dto.getUserCode()
                ;
        return httpRequestGetString(urlString, "关注/取消关注投顾IP",false);
    }
    /**
     * 查询员工所属投顾IP信息
     * @param dto
     */
    public GuoxinInvestmentAdvisorTeamDTO getGuoxinInvestmentAdvisorTeamDTO(GetTghInfoDTO dto) {
        GuoxinInvestmentAdvisorTeamDTO investmentAdvisorTeamDTO = new GuoxinInvestmentAdvisorTeamDTO();
        JSONObject tghInfo = getTghInfo(dto);
        if (Objects.nonNull(tghInfo) && tghInfo.containsKey(GuoXinXtgzstgGetTghInfoResponseEnum.ZONE_ID.getValue())) {
            String zoneId = tghInfo.getString(GuoXinXtgzstgGetTghInfoResponseEnum.ZONE_ID.getValue());
            String zoneName = tghInfo.getString(GuoXinXtgzstgGetTghInfoResponseEnum.ZONE_NAME.getValue());
            String slogan = tghInfo.getString(GuoXinXtgzstgGetTghInfoResponseEnum.SLOGAN.getValue());
            String logo = tghInfo.getString(GuoXinXtgzstgGetTghInfoResponseEnum.LOGO.getValue());
            String isFollow = tghInfo.getString(GuoXinXtgzstgGetTghInfoResponseEnum.IS_FOLLOW.getValue());
            Integer followNum = tghInfo.getInteger(GuoXinXtgzstgGetTghInfoResponseEnum.FOLLOW_NUM.getValue());
            Integer watchNum = tghInfo.getInteger(GuoXinXtgzstgGetTghInfoResponseEnum.WATCH_NUM.getValue());
            investmentAdvisorTeamDTO.setZoneId(zoneId);
            investmentAdvisorTeamDTO.setZoneName(zoneName);
            investmentAdvisorTeamDTO.setSlogan(slogan);
            investmentAdvisorTeamDTO.setLogo(logo);
            investmentAdvisorTeamDTO.setIsFollow(isFollow);
            investmentAdvisorTeamDTO.setFollowNum(followNum);
            investmentAdvisorTeamDTO.setWatchNum(watchNum);
            investmentAdvisorTeamDTO.setInfoUrl(thirdPartyProperties.getTgh().getDetailsUrl()+zoneId);
        }
        return investmentAdvisorTeamDTO;
    }
}
